package com.yeskery.nut.annotation.bean;

import com.yeskery.nut.aop.ProxyType;
import com.yeskery.nut.bean.ApplicationContext;

import java.lang.annotation.*;

/**
 * <p>Bean组件定义注解，通过该注解可以将某个类直接注入到{@link ApplicationContext}中，该注解是bean的完全体，可以处理bean的完整生命周期，
 * 可以使用{@link #value()}指定bean的名称。</p>
 *
 * <p>使用{@link #scope()}方法可以指定bean的范围，默认为{@link ApplicationContext#SCOPE_SINGLETON}，可选值有{@link ApplicationContext#SCOPE_PROTOTYPE}，
 * 用于指定bean是单例还是原型，如果为单例({@link ApplicationContext#SCOPE_SINGLETON})在整个{@link ApplicationContext}生命周期中，将只会有一个bean实例；
 * 如果为原型({@link ApplicationContext#SCOPE_PROTOTYPE})，在每次通过{@link ApplicationContext}获取到的bean都是一个新的bean实例。</p>
 *
 * <p>使用{@link #proxyType()}方法可以指定代理的生成方式，默认为{@link ProxyType#AUTO}，该方式优先会使用cglib进行生成代理，如果cglib的依赖不存在
 * 则会尝试使用jdk代理方式生成代理；如果选择{@link ProxyType#CGLIB}，则使用cglib的方式进行生成代理，但是需要提前引入cglib的依赖jar包，否则将无法生产代理；
 * 如果选择{@link ProxyType#JDK}，则默认使用jdk的方式进行生成代理，在使用jdk方式时需要注入该类型的bean至少需要实现一个接口，因为jdk代理是基于接口方式进行实现的。</p>
 *
 * <p>使用该种方式进行注入，可以使用{@link com.yeskery.nut.bean.InitializingBean}接口或{@link javax.annotation.PostConstruct}
 * 注解在bean初始化完成后执行自定义初始化代码，也可以使用{@link com.yeskery.nut.bean.DisposableBean}接口或{@link javax.annotation.PreDestroy}
 * 注解在bean销毁前执行自定义销毁代码</p>
 * 
 * @see com.yeskery.nut.bean.InitializingBean
 * @see com.yeskery.nut.bean.DisposableBean
 * @see javax.annotation.PostConstruct
 * @see javax.annotation.PreDestroy
 * 
 * @author sprout
 * 2022-06-20 17:17
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {

    /**
     * bean的名称
     * @return bean的名称
     */
    String value() default "";

    /**
     * bean范围
     * @return bean范围
     */
    String scope() default ApplicationContext.SCOPE_SINGLETON;

    /***
     * 如果Bean需要代理，使用的代理类型
     * @return 代理类型
     */
    ProxyType proxyType() default ProxyType.AUTO;
}
